home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 1 / Cream of the Crop 1.iso / PRINTER / JPSRC11.ARJ / JETD2L.C < prev    next >
C/C++ Source or Header  |  1991-08-04  |  15KB  |  490 lines

  1. /*
  2.  *      JET PAK - HP DeskJet and LaserJet series printer utilities
  3.  *
  4.  *      JETD2L program - convert from DeskJet to LaserJet soft font file
  5.  *
  6.  *      Version 1.1 (Public Domain)
  7.  */
  8.  
  9. /* system include files */
  10. #include <stdio.h>
  11. #include <stdlib.h>
  12. #include <string.h>
  13. #include <ctype.h>
  14.  
  15. /* application include files */
  16. #include "patchlev.h"
  17. #include "jetfont.h"
  18. #include "jetutil.h"
  19. #include "jetbmp.h"
  20.  
  21. /*
  22.  *  MODULE GLOBAL DATA
  23.  */
  24.  
  25. /* baseline distance for bottom pass */
  26. static UNSIGNEDINT baseline;
  27.  
  28. /* pitch is needed for converting landscape characters */
  29. static UNSIGNEDINT pitch;
  30.  
  31. /* height to use for all characters */
  32. static UNSIGNEDINT cell_height;
  33.  
  34. /* offsets for passes */
  35. static UNSIGNEDINT offsets[4];
  36.  
  37. /* portrait or landscape font */
  38. static UNSIGNEDBYTE orientation;
  39.  
  40. /* fixed or proportional spacing font */
  41. static UNSIGNEDINT spacing;
  42.  
  43. /* input and output font commands being processed */
  44. static FONT_COMMAND infc, outfc;
  45.  
  46. /* output file suffix */
  47. static char output_suffix[SUFFIX_MAX] = ".d2l";
  48.  
  49. /* compact bitmap structure */
  50. typedef struct compact_ljchar_struct {
  51.     SIGNEDINT    left_offset;
  52.     SIGNEDINT    top_offset;
  53.     UNSIGNEDINT  character_width;
  54.     UNSIGNEDINT  character_height;
  55.     SIGNEDINT    delta_x;
  56.     UNSIGNEDBYTE *bitmap;
  57. } COMPACT_LJCHAR;
  58. static COMPACT_LJCHAR ljchars[256] = { 0 };
  59. #define sizeofljbitmap(w,h) (((w + 7)/8)*h)
  60.  
  61. /*
  62.  * LOCAL FUNCTIONS
  63.  */
  64.  
  65. static void usage_wrong()
  66. {
  67.     /*
  68.      * Print usage message and exit.
  69.      */
  70.     fprintf(stderr, USAGE_HEADER);
  71.     fprintf(stderr, "Usage: JETD2L [-h] [-t filetype] djfontfile [djfontfile...]\n\n");
  72.     fprintf(stderr, "Convert DeskJet font files to LaserJet format\n\n");
  73.     fprintf(stderr, "  -h            print this usage information\n");
  74.     fprintf(stderr, "  -t filetype   change output file type (default %s)\n", output_suffix);
  75.     fprintf(stderr, "  djfontfile    name of DeskJet format soft font file to be converted\n");
  76.     exit(1);
  77. }
  78.  
  79. static int ljchar_create(charcode, infcp)
  80. UNSIGNEDINT charcode;
  81. FONT_COMMAND *infcp;
  82. {
  83.     /*
  84.      * Copy the information in a DeskJet character descriptor to
  85.      * a compact LaserJet character structure, allocating space
  86.      * for the bitmap if necessary.
  87.      */
  88.     struct djchar_struct *djp;
  89.     UNSIGNEDINT height;
  90.     int pass;
  91.  
  92.     /* issue a warning if the character descriptor is in a strange format */
  93.     if (    (infcp->data.character.format != DJCHARFORMAT)
  94.          && (infcp->data.character.format != DJPCHARFORMAT)
  95.          && (infcp->data.character.format != DJ500CHARFORMAT) )
  96.         fprintf(stderr, WARNING_BAD_CHAR_FORMAT,
  97.                 os_dir, os_file, infcp->data.character.format);
  98.  
  99.     /* check the character code is in range */
  100.     if (charcode >= sizeofarray(ljchars))
  101.     {
  102.         fprintf(stderr, ERROR_CODE_TOO_BIG, os_dir, os_file, charcode);
  103.         return(ERROR);
  104.     }
  105.  
  106.     /* OK to save the information */
  107.     djp = &infcp->data.character.data.djchar;
  108.     switch (djp->char_type)
  109.     {
  110.     case CHAR_TYPE_NORMAL:
  111.     case CHAR_TYPE_PASS1:
  112.         if (orientation == LANDSCAPE)
  113.         {
  114.             ljchars[charcode].left_offset = djp->comp_width/2 - baseline;
  115.             ljchars[charcode].top_offset = pitch;
  116.             ljchars[charcode].character_width = djp->character_width/2;
  117.             ljchars[charcode].character_height = pitch;
  118.             ljchars[charcode].delta_x = pitch*4;
  119.         }
  120.         else
  121.         {
  122.             ljchars[charcode].top_offset = baseline;
  123.             ljchars[charcode].character_width = djp->character_width/2;
  124.             ljchars[charcode].character_height = cell_height;
  125.             if (spacing == FIXED)
  126.             {
  127.                 ljchars[charcode].delta_x = pitch*4;
  128.                 ljchars[charcode].left_offset = ((SIGNEDINT)(pitch - djp->character_width/2))/2;
  129.             }
  130.             else
  131.             {
  132.                 ljchars[charcode].delta_x = 2 * (   djp->right_offset
  133.                                                   + djp->left_offset
  134.                                                   + djp->character_width);
  135.                 ljchars[charcode].left_offset = djp->left_offset/2;
  136.             }
  137.         }
  138.  
  139.         if ((ljchars[charcode].bitmap =
  140.             zalloc(sizeofljbitmap(ljchars[charcode].character_width, ljchars[charcode].character_height))) == NULL)
  141.         {
  142.             fprintf(stderr, ERROR_FONT_OUT_OF_HEAP, os_dir, os_file);
  143.             return(ERROR);
  144.         }
  145.  
  146.         /* !! intentional drop-through !! */
  147.     default:
  148.         pass = pass_for_char_type(djp->char_type) % sizeofarray(offsets);
  149.  
  150.         height = ljchars[charcode].character_height - offsets[pass];
  151.         if (height > PASS_HEIGHT)
  152.             height = PASS_HEIGHT;
  153.  
  154.         if (bitmap_dj_to_lj(djp->bitmap, djp->character_width, height,
  155.             offsets[pass], ljchars[charcode].bitmap,
  156.             sizeofljbitmap(ljchars[charcode].character_width,
  157.                         ljchars[charcode].character_height)) != OK)
  158.         {
  159.             fprintf(stderr, ERROR_BITMAP_TOO_BIG, os_dir, os_file);
  160.             return(ERROR);
  161.         }
  162.     }
  163.  
  164.     return(OK);
  165. }
  166.  
  167. static void ljchar_free_all()
  168. {
  169.     /*
  170.      * Free the resources used in all the compact LaserJet characters.
  171.      */
  172.     UNSIGNEDINT charcode;
  173.  
  174.     for (charcode = 0; charcode < sizeofarray(ljchars); charcode++)
  175.     {
  176.         if (ljchars[charcode].bitmap != NULL)
  177.         {
  178.             free(ljchars[charcode].bitmap);
  179.             ljchars[charcode].bitmap = NULL;
  180.         }
  181.     }
  182. }
  183.  
  184. static int fdc_dj_to_lj(infcp, outfcp)
  185. FONT_COMMAND *infcp, *outfcp;
  186. {
  187.     /*
  188.      * Convert a DeskJet font descriptor command to a LaserJet font
  189.      * descriptor command.
  190.      */
  191.     int passes;
  192.     FONT_DESCRIPTOR *fdp;
  193.  
  194.     /* check input file is in correct format */
  195.     if (infcp->data.font.header_format == LJFONTFORMAT)
  196.     {
  197.         fprintf(stderr, ERROR_LASERJET, os_dir, os_file);
  198.         return(ERROR);
  199.     }
  200.     else if (    (infcp->data.font.header_format != DJFONTFORMAT)
  201.               && (infcp->data.font.header_format != DJPFONTFORMAT)
  202.               && (infcp->data.font.header_format != DJ500FONTFORMAT) )
  203.     {
  204.         fprintf(stderr, WARNING_BAD_FONT_FORMAT,
  205.                 os_dir, os_file, infcp->data.font.header_format);
  206.     }
  207.  
  208.     outfcp->command_type = infcp->command_type;
  209.     outfcp->number = LJFDSIZE+LJSSIZE;
  210.  
  211.     /* most of the font descriptor fields can be copied straight
  212.        across */
  213.     outfcp->data.font = infcp->data.font;
  214.  
  215.     /* now change the standard font descriptor bits that are different */
  216.     fdp = &outfcp->data.font;
  217.     fdp->header_format = LJFONTFORMAT;
  218.     fdp->size = LJFDSIZE;
  219.  
  220.     /* convert the bitmap related data - depends on orientation */
  221.     if (fdp->orientation == LANDSCAPE)
  222.     {
  223.         fdp->cell_height /= 2;  /* -> 300 dpi in X direction */
  224.  
  225.         /* must be a single pass font */
  226.         passes = 1;
  227.         offsets[0] = 0;
  228.         offsets[1] = 0;
  229.         offsets[2] = 0;
  230.         offsets[3] = 0;
  231.     }
  232.     else    /* PORTRAIT */
  233.     {
  234.         /* save the pass offsets */
  235.         if (fdp->baseline_offset_4 != 0)
  236.         {
  237.             passes = 4;
  238.             offsets[0] = fdp->baseline_offset_4 - fdp->baseline_distance;
  239.             offsets[1] = fdp->baseline_offset_4 - fdp->baseline_offset_2;
  240.             offsets[2] = fdp->baseline_offset_4 - fdp->baseline_offset_3;
  241.             offsets[3] = 0;
  242.             fdp->baseline_distance = fdp->baseline_offset_4;
  243.         }
  244.         else if (fdp->baseline_offset_3 != 0)
  245.         {
  246.             passes = 3;
  247.             offsets[0] = fdp->baseline_offset_3 - fdp->baseline_distance;
  248.             offsets[1] = fdp->baseline_offset_3 - fdp->baseline_offset_2;
  249.             offsets[2] = 0;
  250.             offsets[3] = 0;
  251.             fdp->baseline_distance = fdp->baseline_offset_3;
  252.         }
  253.         else if (fdp->baseline_offset_2 != 0)
  254.         {
  255.             passes = 2;
  256.             offsets[0] = fdp->baseline_offset_2 - fdp->baseline_distance;
  257.             offsets[1] = 0;
  258.             offsets[2] = 0;
  259.             offsets[3] = 0;
  260.             fdp->baseline_distance = fdp->baseline_offset_2;
  261.         }
  262.         else
  263.         {
  264.             passes = 1;
  265.             offsets[0] = 0;
  266.             offsets[1] = 0;
  267.             offsets[2] = 0;
  268.             offsets[3] = 0;
  269.         }
  270.  
  271.         fdp->cell_width /= 2;   /* -> 300 dpi in X direction */
  272.  
  273.         fdp->cell_height = offsets[0] + PASS_HEIGHT;
  274.     }
  275.  
  276.     /* save parameters needed in character descriptor processing */
  277.     baseline = fdp->baseline_distance;
  278.     pitch = fdp->pitch/4;
  279.     orientation = fdp->orientation;
  280.     cell_height = fdp->cell_height;
  281.     spacing = fdp->spacing;
  282.  
  283.     /* add identifying suffix to existing copyright notice */
  284.     if ((strlen(fdp->comment) + sizeof(JETD2L_COMMENT_SUFFIX)) < COMMENT_SIZE_MAX)
  285.         strcat(fdp->comment, JETD2L_COMMENT_SUFFIX);
  286.     outfcp->number += strlen(fdp->comment);
  287.  
  288.     return(passes);
  289. }
  290.  
  291. static int cdc_dj_to_lj(inccp, outfcp)
  292. COMPACT_LJCHAR *inccp;
  293. FONT_COMMAND *outfcp;
  294. {
  295.     /*
  296.      * Copy a compact LaserJet character to a real LaserJet character
  297.      * descriptor.
  298.      */
  299.     struct ljchar_struct *ljp;
  300.  
  301.     outfcp->command_type = CDC;
  302.  
  303.     /* deal with the preamble bits */
  304.     outfcp->data.character.format = LJCHARFORMAT;
  305.     outfcp->data.character.continuation = 0;
  306.  
  307.     /* deal with the character descriptor proper */
  308.     ljp = &outfcp->data.character.data.ljchar;
  309.     ljp->descriptor_size = LJCDSIZE;
  310.     ljp->class = 1;
  311.     ljp->orientation = orientation;
  312.     ljp->reserved = 0;
  313.     ljp->left_offset = inccp->left_offset;
  314.     ljp->top_offset = inccp->top_offset;
  315.     ljp->character_width = inccp->character_width;
  316.     ljp->character_height = inccp->character_height;
  317.     ljp->delta_x = inccp->delta_x;
  318.  
  319.     memcpy(ljp->bitmap, inccp->bitmap,
  320.             sizeofljbitmap(ljp->character_width, ljp->character_height));
  321.     outfcp->number = 2 + LJCDSIZE + sizeofljbitmap(ljp->character_width, ljp->character_height);
  322.  
  323.     return(OK);
  324. }
  325.  
  326. static void jetd2l()
  327. {
  328.     char inpath[OS_PATH_LEN], outpath[OS_PATH_LEN], *sp;
  329.     FILE *infp, *outfp;
  330.     int r, npasses = 0;
  331.     UNSIGNEDINT charcode;
  332.  
  333.     /* build the input and output file paths */
  334.     strcpy(inpath, os_dir);
  335.     strcat(inpath, os_file);
  336.     strcpy(outpath, os_file);
  337.     if ((sp = strrchr(outpath, '.')) == NULL)
  338.         strcat(outpath, output_suffix);
  339.     else
  340.         strcpy(sp, output_suffix);
  341.  
  342.     /* rudimentary check for input overwriting output */
  343.     if (strcmp(inpath, outpath) == 0)
  344.     {
  345.         fprintf(stderr, ERROR_OVERWRITE, os_dir, os_file);
  346.         return;
  347.     }
  348.  
  349.     if (!(infp = fopen(inpath, "rb")))
  350.     {
  351.         fprintf(stderr, ERROR_OPEN_READ_FAILED, os_dir, os_file);
  352.         return;
  353.     }
  354.     if (!(outfp = fopen(outpath, "wb")))
  355.     {
  356.         fprintf(stderr, ERROR_OPEN_WRITE_FAILED, os_dir, os_file, outpath);
  357.         fclose(infp);
  358.         return;
  359.     }
  360.  
  361.     /* copy the font header and load the characters into memory */
  362.     while ((r = font_command_read(infp, &infc)) == OK)
  363.     {
  364.         switch(infc.command_type)
  365.         {
  366.         case FDC:
  367.             if ((npasses = fdc_dj_to_lj(&infc, &outfc)) == ERROR)
  368.             {
  369.                 ljchar_free_all();
  370.                 fclose(infp);
  371.                 fclose(outfp);
  372.                 return;
  373.             }
  374.             if (font_command_write(outfp, &outfc) == ERROR)
  375.             {
  376.                 fprintf(stderr, ERROR_FILE_WRITE_FAILED, os_dir, os_file);
  377.                 ljchar_free_all();
  378.                 fclose(infp);
  379.                 fclose(outfp);
  380.                 return;
  381.             }
  382.             break;
  383.         case CCC:
  384.             charcode = infc.number;
  385.             break;
  386.         case CDC:
  387.             if (ljchar_create(charcode, &infc) == ERROR)
  388.             {
  389.                 ljchar_free_all();
  390.                 fclose(infp);
  391.                 fclose(outfp);
  392.                 return;
  393.             }
  394.             break;
  395.         }
  396.     }
  397.  
  398.     if (npasses > 0)
  399.     {
  400.         for (charcode = 0; charcode < sizeofarray(ljchars); charcode++)
  401.         {
  402.             if (ljchars[charcode].bitmap != NULL)
  403.             {
  404.                 /* output the character code command */
  405.                 outfc.command_type = CCC;
  406.                 outfc.number = charcode;
  407.                 if (font_command_write(outfp, &outfc) == ERROR)
  408.                 {
  409.                     fprintf(stderr, ERROR_FILE_WRITE_FAILED, os_dir, os_file);
  410.                     ljchar_free_all();
  411.                     fclose(infp);
  412.                     fclose(outfp);
  413.                     return;
  414.                 }
  415.  
  416.                 /* convert the character descriptor and bitmap */
  417.                 if (cdc_dj_to_lj(&ljchars[charcode], &outfc) == ERROR)
  418.                 {
  419.                     ljchar_free_all();
  420.                     fclose(infp);
  421.                     fclose(outfp);
  422.                     return;
  423.                 }
  424.  
  425.                 /* output the character descriptor and bitmap */
  426.                 if (font_command_write(outfp, &outfc) == ERROR)
  427.                 {
  428.                     fprintf(stderr, ERROR_FILE_WRITE_FAILED, os_dir, os_file);
  429.                     ljchar_free_all();
  430.                     fclose(infp);
  431.                     fclose(outfp);
  432.                     return;
  433.                 }
  434.             }
  435.         }
  436.     }
  437.  
  438.     if (npasses == 0 || r != EOF)
  439.         /* error scenarios: (npasses == 0) means no font descriptor found,
  440.            probably processing a text file; (r != EOF) means a font
  441.            command escape sequence wasn't read in correctly, probably
  442.            processing a binary file or a truncated soft font file */
  443.         fprintf(stderr, ERROR_FILE_READ_FAILED, os_dir, os_file);
  444.     else
  445.     {
  446.         fprintf(stderr, OK_JETD2L, os_dir, os_file, outpath);
  447.     }
  448.  
  449.     ljchar_free_all();
  450.     fclose(infp);
  451.     fclose(outfp);
  452. }
  453.  
  454. main(argc, argv)
  455. int argc;
  456. char *argv[];
  457. {
  458.     char c;
  459.  
  460.     /* stop getopt() printing errors */
  461.     opterr = FALSE;
  462.     while ((c = getopt(argc, argv, "t:h")) != EOF)
  463.     {
  464.         switch (c)
  465.         {
  466.         case 't':
  467.             strncpy(output_suffix+1, optarg, SUFFIX_MAX-2);
  468.             output_suffix[SUFFIX_MAX-1] = '\0';
  469.             break;
  470.         case 'h':
  471.         case '?':
  472.             /* help required, or invalid option specified */
  473.             usage_wrong();
  474.         }
  475.     }
  476.  
  477.     /* must specify at least one file */
  478.     if (optind >= argc)
  479.         usage_wrong();
  480.  
  481.     /* process file arguments */
  482.     if (os_findfiles((argc - optind), &argv[optind]) == ERROR)
  483.         fprintf(stderr, ERROR_OUT_OF_HEAP);
  484.  
  485.     while (os_getfile() != EOF)
  486.         jetd2l();
  487.  
  488.     return(0);
  489. }
  490.